#include <vcl.h>
#include <Printers.hpp>
#include <math.h>
#pragma hdrstop

#include "Eic.h"
#include "MTAG_CtrlStd.h"
#include "CRtfEdit.h"
#include "uSousClasse.h" //Pour TSousClassage
#pragma package(smart_init)

#define MODULE_TAG MTAG_CRTFEDIT

#define MM_PER_INCH 25.4 //25.4 mm = 1 pouce

// Délimiteurs respectant le format RTF
////////////////////////////////////////////////////////////////////////////////
#define DELIMIT_LARG_FEUILLE "\\paperw"    //Largeur de la page
#define DELIMIT_HAUT_FEUILLE "\\paperh"    //Hauteur de la page

#define DELIMIT_MARG_G "\\margl" //Marge gauche
#define DELIMIT_MARG_D "\\margr" //Marge droite
#define DELIMIT_MARG_H "\\margt" //Marge haut
#define DELIMIT_MARG_B "\\margb" //Marge bas

//#define DELIMIT_PAYSAGE      "\\landscape" //Orientation en mode paysage
#define DELIMIT_SECT_PAYSAGE      "\\lndscpsxn" //Orientation en mode paysage de la section

#define DELIMIT_HAUT_EN_TETE      "\\headery" //Position de l'en tête par rapport au bord haut
#define DELIMIT_HAUT_PIED_DE_PAGE "\\footery" //Position du pied de page par rapport au bord bas

#define DECALAGE_X_RICH_EDIT 2
//---------------------------------------------------------------------------
static int _HauteurVoulueParRichEdit; //Hauteur voulue en pixels




void __fastcall TRichEditSansAutoScroll::CreateParams(Controls::TCreateParams &Params)
{
inherited::CreateParams(Params);
Params.Style &= ~ES_AUTOVSCROLL;
}

// ValidCtrCheck est utilisé est utilisé pour être sûr que les composants créés n'ont
// aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CRtfEdit *)
{
   new CRtfEdit(NULL);
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
AnsiString BinToHexa(const char *szBin, unsigned iNbChar)
{
char *szRtfHexa = NULL;
int iPosHex = 0;
char szOctet[3];
AnsiString aRetour;

try
   {
   szRtfHexa    = new char[iNbChar*2];
   memset(szRtfHexa, 0, iNbChar*2);

   for (unsigned i = 0 ; i < iNbChar ; i++)
      {
      strcpy(szOctet, IntToHex((unsigned char)szBin[i], 2).c_str());

      //On stock dans un char* pour optimiser la vitesse
      szRtfHexa[iPosHex  ] = szOctet[0];
      szRtfHexa[iPosHex+1] = szOctet[1];
      iPosHex+=2;
      }

   aRetour = szRtfHexa;
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(20), e);
   }

if (szRtfHexa)
   {
   delete []szRtfHexa;
   szRtfHexa = NULL;
   }
return aRetour;
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
AnsiString BitmapVersRTF(Graphics::TBitmap *pict)
{
unsigned int OctetsBitmapInfo, OctetsBitmapBits;
AnsiString aRtf;
char *szBin = NULL;

try
   {
   GetDIBSizes(pict->Handle, OctetsBitmapInfo, OctetsBitmapBits);

   szBin        = new char[(OctetsBitmapInfo + OctetsBitmapBits)];
   if (GetDIB(pict->Handle, pict->Palette, &szBin[0], &szBin[OctetsBitmapInfo]))
      aRtf = "{\\rtf1 {\\pict\\dibitmap " + BinToHexa(szBin, OctetsBitmapInfo + OctetsBitmapBits) + " }}";
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(30), e);
   }
if (szBin)
   delete []szBin;

return aRtf;
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
__fastcall CRtfEdit::CRtfEdit(TComponent* Owner)
   : TCustomPanel(Owner)
{
try
   {
   m_MargeG = 25;
   m_MargeD = 25;
   m_MargeH = 25;
   m_MargeB = 25;

   m_PapierH = 297;
   m_PapierL = 210;

   m_dPositionEnTete = 12.7;
   m_dPositionPiedDePage = 12.7;
   m_Format = ::A4;
   m_PopupMenu = NULL;

   m_ContrainteTaille = new TContrainteTailleRichEdit(&ContrainteHauteurChange, &ContrainteMargeChange);

   Height                       = m_PapierH * Screen->PixelsPerInch / MM_PER_INCH;
   Width                        = m_PapierL * Screen->PixelsPerInch / MM_PER_INCH;
   BevelInner = bvNone;
   BevelOuter = bvNone;
   m_Color                      = clWindow;
   m_AfficherEnTeteEtPiedDePage = false;
   m_PlainText                  = false;
   m_ReadOnly                   = false;
   m_HideSelection              = true;
   m_WantReturns                = true;
   m_WantTabs                   = true;
   m_WordWrap                   = true;
   
   inherited::Color             = m_Color;
   m_CGB_EnTete                 = NULL;
   m_CGB_EnTete                 = new CGroupBox(this);
   m_CGB_EnTete->Parent         = this;
   m_CGB_EnTete->Visible        = false;
   m_CGB_EnTete->Caption        = " En tête ";
   m_CGB_EnTete->BordHautTransparent = false;
   m_CGB_EnTete->Color          = m_Color;

   m_RE_EnTete                  = NULL;
   m_RE_EnTete                  = new TRichEditSansAutoScroll(this);
   m_RE_EnTete->Parent          = m_CGB_EnTete;
   m_RE_EnTete->Align           = alClient;
   m_RE_EnTete->BorderStyle     = bsNone;
   m_RE_EnTete->OnChange        = RichEditChange;
   m_RE_EnTete->OnKeyDown       = RichEditKeyDown;
   m_RE_EnTete->OnKeyUp         = RichEditKeyUp;
   m_RE_EnTete->OnKeyPress      = RichEditKeyPress;
   m_RE_EnTete->OnSelectionChange = RichEditSelectionChange;
   m_RE_EnTete->OnEnter         = RichEditOnEnter;

   m_RE_Corps                   = NULL;
   m_RE_Corps                   = new TRichEditSansAutoScroll(this);
   m_RE_Corps->Parent           = this;
   m_RE_Corps->BorderStyle      = bsNone;
   m_RE_Corps->OnChange         = RichEditChange;
   m_RE_Corps->OnKeyDown        = RichEditKeyDown;
   m_RE_Corps->OnKeyUp          = RichEditKeyUp;
   m_RE_Corps->OnKeyPress       = RichEditKeyPress;
   m_RE_Corps->OnSelectionChange = RichEditSelectionChange;
   m_RE_Corps->OnEnter          = RichEditOnEnter;
   m_RE_Corps->Modified         = false;

   m_CGB_PiedDePage             = NULL;
   m_CGB_PiedDePage             = new CGroupBox(this);
   m_CGB_PiedDePage->Parent     = this;
   m_CGB_PiedDePage->Visible    = false;
   m_CGB_PiedDePage->Caption    = " Pied de page ";
   m_CGB_PiedDePage->BordHautTransparent = false;
   m_CGB_PiedDePage->Color      = m_Color;

   m_RE_PiedDePage              = NULL;
   m_RE_PiedDePage              = new TRichEditSansAutoScroll(this);
   m_RE_PiedDePage->Parent      = m_CGB_PiedDePage;
   m_RE_PiedDePage->Align       = alClient;
   m_RE_PiedDePage->BorderStyle = bsNone;
   m_RE_PiedDePage->OnChange    = RichEditChange;
   m_RE_PiedDePage->OnKeyDown   = RichEditKeyDown;
   m_RE_PiedDePage->OnKeyUp     = RichEditKeyUp;
   m_RE_PiedDePage->OnKeyPress  = RichEditKeyPress;
   m_RE_PiedDePage->OnSelectionChange = RichEditSelectionChange;
   m_RE_PiedDePage->OnEnter     = RichEditOnEnter;
   m_RE_PiedDePage->Modified    = false;

   m_RE_Courant = m_RE_Corps;
   m_RE_DernierModifie          = NULL;

   m_LinesEnTete                = NULL;
   m_LinesEnTete                = new TStringList();
   m_LinesCorps                 = NULL;
   m_LinesCorps                 = new TStringList();
   m_LinesPiedDePage            = NULL;
   m_LinesPiedDePage            = new TStringList();
   m_OnChange                   = NULL;
   m_OnKeyDown                  = NULL;
   m_OnKeyPress                 = NULL;
   m_OnKeyUp                    = NULL;
   m_OnSelectionChange          = NULL;
   m_OnResizeRequest            = NULL;
   m_OnGetHDCImp                = NULL;
   m_Modified                   = false;
   m_RE_PiedDePage->WantTabs    = true;
   m_RE_EnTete->WantTabs        = true;
   m_RE_Corps->WantTabs         = true;
   _HauteurVoulueParRichEdit    = -1;
   m_SveWindowProcEnTete         = m_CGB_EnTete->WindowProc;
   m_SveWindowProcPiedDePage     = m_CGB_PiedDePage->WindowProc;
   m_SveWindowProcCorps          = WindowProc;
   m_CGB_EnTete->WindowProc      = MyWndProcParentEnTete;
   m_CGB_PiedDePage->WindowProc  = MyWndProcParentPiedDePage;
   WindowProc                    = MyWndProcParentCorps;
   if(ComponentState.Contains(csDesigning))
      PositionnerPanelRichEdit();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(100), e);
   }
}

__fastcall CRtfEdit::~CRtfEdit()
{
try
   {
   m_CGB_EnTete->WindowProc = m_SveWindowProcEnTete;
   m_CGB_PiedDePage->WindowProc = m_SveWindowProcPiedDePage;
   WindowProc = m_SveWindowProcCorps;

   if (m_RE_EnTete)
     delete m_RE_EnTete;
   if (m_CGB_EnTete)
     delete m_CGB_EnTete;
   if (m_RE_Corps)
     delete m_RE_Corps;
   if (m_RE_PiedDePage)
     delete m_RE_PiedDePage;
   if (m_CGB_PiedDePage)
     delete m_CGB_PiedDePage;
   if (m_LinesEnTete)
     delete m_LinesEnTete;
   if (m_LinesCorps)
     delete m_LinesCorps;
   if (m_LinesPiedDePage)
     delete m_LinesPiedDePage;


   if (m_ContrainteTaille)
      delete m_ContrainteTaille;
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(110), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres modifiés :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::LoadFromString(const char szRTF[])
{
enum TypeControle
   {
   eAUCUN,
   eMARGE_HAUT,
   eMARGE_BAS,
   eMARGE_DROITE,
   eMARGE_GAUCHE,
   eFEUILLE_HAUTEUR,
   eFEUILLE_LARGEUR,
//   eORIENTATION_SECT_PAYSAGE,
   eHAUTEUR_EN_TETE,
   eHAUTEUR_PIED_DE_PAGE,
   };

TStringStream *ssTexte = NULL;
int i;
int shNiv = 0;
AnsiString aChaineATraiter;
int lValeurLu;
AnsiString LignesEnTete, LignesPiedDePage;
TCursor SveCursor;
AnsiString aPoliceDefaut;
#ifdef _DEBUG
int iLigne = TAGL;
#endif
try
   {
   //Affiche le sablier
   SveCursor      = Screen->Cursor;
   Screen->Cursor = crHourGlass;

   //On stocke le contenu du fichier dans szRTF
   /////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
   iLigne = TAGL;
#endif

   //On va scruter la chaîne à la recherche des paramètres qui nous intéresse
   /////////////////////////////////////////////////////////////////////////////
//   m_bIsPortrait = true; //On initialise en orientation portrait par défaut.

#ifdef _DEBUG
   iLigne = TAGL;
#endif
   i=0;
   do
      {
      if (szRTF[i] == '{' && (i == 0 || szRTF[i-1] != '\\'))
         shNiv++;

      //SI nous sommes sur un paramètre de 1er niveau
      if (shNiv == 1 && szRTF[i] == '\\' && (i == 0 || szRTF[i-1] != '\\'))
         {
         TypeControle eTypeControleDetecte = eAUCUN;

         //SI le caractère courant correspond au début d'un contrôle
         if (strncmpi(&szRTF[i], DELIMIT_HAUT_FEUILLE, strlen(DELIMIT_HAUT_FEUILLE)) == 0)
            {
            eTypeControleDetecte = eFEUILLE_HAUTEUR;
            i += strlen(DELIMIT_HAUT_FEUILLE); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_LARG_FEUILLE, strlen(DELIMIT_LARG_FEUILLE)) == 0)
            {
            eTypeControleDetecte = eFEUILLE_LARGEUR;
            i += strlen(DELIMIT_LARG_FEUILLE); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_MARG_G, strlen(DELIMIT_MARG_G)) == 0)
            {
            eTypeControleDetecte = eMARGE_GAUCHE;
            i += strlen(DELIMIT_MARG_G); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_MARG_D, strlen(DELIMIT_MARG_D)) == 0)
            {
            eTypeControleDetecte = eMARGE_DROITE;
            i += strlen(DELIMIT_MARG_D); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_MARG_H, strlen(DELIMIT_MARG_H)) == 0)
            {
            eTypeControleDetecte = eMARGE_HAUT;
            i += strlen(DELIMIT_MARG_H); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_MARG_B, strlen(DELIMIT_MARG_B)) == 0)
            {
            eTypeControleDetecte = eMARGE_BAS;
            i += strlen(DELIMIT_MARG_B); //Positionnement sur le caractère qui suit le contrôle
            }
//         else if (strncmpi(&szRTF[i], DELIMIT_SECT_PAYSAGE, strlen(DELIMIT_SECT_PAYSAGE)) == 0)
//            eTypeControleDetecte = eORIENTATION_SECT_PAYSAGE;
         else if (strncmpi(&szRTF[i], DELIMIT_HAUT_EN_TETE, strlen(DELIMIT_HAUT_EN_TETE)) == 0)
            {
            eTypeControleDetecte = eHAUTEUR_EN_TETE;
            i += strlen(DELIMIT_HAUT_EN_TETE); //Positionnement sur le caractère qui suit le contrôle
            }
         else if (strncmpi(&szRTF[i], DELIMIT_HAUT_PIED_DE_PAGE, strlen(DELIMIT_HAUT_PIED_DE_PAGE)) == 0)
            {
            eTypeControleDetecte = eHAUTEUR_PIED_DE_PAGE;
            i += strlen(DELIMIT_HAUT_PIED_DE_PAGE); //Positionnement sur le caractère qui suit le contrôle
            }

         if (eTypeControleDetecte != eAUCUN)
            {
/*            if (eTypeControleDetecte == eORIENTATION_SECT_PAYSAGE)
               m_bIsPortrait = false;
            else*/
               {
               aChaineATraiter = '0';   //Si aucune valeur numérique n'est détectée, elle sera à 0
               //On récupère la valeur numérique qui suit le contrôle
               while(szRTF[i] != '\\' && szRTF[i] != '}' && szRTF[i] != '\0')
                  {
                  aChaineATraiter += szRTF[i];
                  i++;
                  }
               i--;

               try{
                  lValeurLu = aChaineATraiter.Trim().ToInt();
                  }
               catch (EConvertError &e)
                  {
                  lValeurLu = -1;
                  ASSERT(false);
                  }

   #ifdef _DEBUG
      iLigne = TAGL;
   #endif
               if (lValeurLu != -1)
                  {
                  //Conversion des Twips lus en Millimètre
                  //(1 Twips = 1/1440 pouces et 1 pouce = 25,4 mm)
                  lValeurLu = lArrond(lValeurLu*MM_PER_INCH/1440.0);

                  switch(eTypeControleDetecte)
                     {
                     case eFEUILLE_HAUTEUR:
                        m_PapierH = lValeurLu;
                        break;
                     case eFEUILLE_LARGEUR:
                        m_PapierL = lValeurLu;
                        break;
                     case eMARGE_GAUCHE:
                        if (m_ContrainteTaille->MargeG == SANS_CONTRAINTE)
                           m_MargeG = lValeurLu;
                        break;
                     case eMARGE_DROITE:
                        if (m_ContrainteTaille->MargeD == SANS_CONTRAINTE)
                           m_MargeD = lValeurLu;
                        break;
                     case eMARGE_HAUT:
                        if (m_ContrainteTaille->MargeH == SANS_CONTRAINTE)
                           m_MargeH = lValeurLu;
                        break;
                     case eMARGE_BAS:
                        if (m_ContrainteTaille->MargeB == SANS_CONTRAINTE)
                           m_MargeB = lValeurLu;
                        break;
                     case eHAUTEUR_EN_TETE:
                        m_dPositionEnTete = lValeurLu;
                        break;
                     case eHAUTEUR_PIED_DE_PAGE:
                        m_dPositionPiedDePage = lValeurLu;
                        break;
                     default : ASSERT(false);
                     }
                  }
               }
            }
         }

#ifdef _DEBUG
   iLigne = TAGL;
#endif
      if (szRTF[i] == '}' && (i == 0 || szRTF[i-1] != '\\'))
         shNiv--;
      i++;
      }
      //TANT que nous n'avons pas fini de scruter la chaine
      //ET QUE nous sommes dans le premier "paragraphe" du RTF
      while (szRTF[i] != '\0' && shNiv != 0);

#ifdef _DEBUG
   iLigne = TAGL;
#endif
   // Chargement du corps du texte
   ssTexte = new TStringStream(szRTF);
   m_RE_Corps->Lines->LoadFromStream(ssTexte);
   aPoliceDefaut = GereRTF.ChercherNomPolice(szRTF);
   m_RE_Corps->Modified = false;
   delete ssTexte; ssTexte = NULL;

#ifdef _DEBUG
   iLigne = TAGL;
#endif
   // Chargement de l'en-tête
   GereRTF.CreerUnRTFPourUneSection(AnsiString(szRTF).Trim(), EN_TETE, &LignesEnTete);
   ssTexte = new TStringStream(LignesEnTete);
   m_RE_EnTete->Font->Name = aPoliceDefaut;
   m_RE_EnTete->Lines->LoadFromStream(ssTexte);
   m_RE_EnTete->Modified        = false;
   delete ssTexte; ssTexte = NULL;

#ifdef _DEBUG
   iLigne = TAGL;
#endif

   // Chargement du pied de page
   GereRTF.CreerUnRTFPourUneSection(AnsiString(szRTF).Trim(), PIED_DE_PAGE, &LignesPiedDePage);
   ssTexte = new TStringStream(LignesPiedDePage);
   m_RE_PiedDePage->Lines->LoadFromStream(ssTexte);
   m_RE_PiedDePage->Modified = false;
   delete ssTexte; ssTexte = NULL;

#ifdef _DEBUG
   iLigne = TAGL;
#endif
   PositionnerPanelRichEdit(); //Pour se repositionner en fonction des marges
   }
catch(Exception &e)
   {
#ifdef _DEBUG
   EICDisplayException(TAG(iLigne), e);
#else
   EICDisplayException(TAG(120), e);
#endif
   }
Screen->Cursor = SveCursor;
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::LoadFromFile(const AnsiString &aFileName)
{
char *szBuffer = NULL;
int hFile = NULL;
int iTailleFichier = 0;
try
   {
   if ((hFile = FileOpen(aFileName, fmOpenRead)) < 1)
      throw EFOpenError("Impossible d'ouvrir le fichier " + aFileName);

   iTailleFichier = FileSeek(hFile, 0, 2);
   FileSeek(hFile, 0, 0);

   szBuffer = new char[iTailleFichier+1];
   FileRead(hFile, szBuffer, iTailleFichier);
   szBuffer[iTailleFichier] = '\0';

   FileClose(hFile);
   hFile = NULL;

   LoadFromString(szBuffer);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(125), e);
   }

delete []szBuffer;         szBuffer = NULL;
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres modifiés :

Valeur retournée :
*******************************************************************************/
AnsiString __fastcall CRtfEdit::SaveToString()
{
TStringStream *ssTexte = NULL;
AnsiString aTexte, aTexteEnTete, aTextePiedDePage,strLigne,strToto;
int i;
try
   {
   //Récupération du corps au format RTF.
   ssTexte = new TStringStream(EmptyStr);
   m_RE_Corps->Lines->SaveToStream(ssTexte);
   aTexte.SetLength(ssTexte->Size);
   ssTexte->Position = 0;
   ssTexte->Read(aTexte.c_str(), ssTexte->Size);
   delete ssTexte; ssTexte = NULL;

   //On y ajoute les contrôles qui ont été effacés par le TRichEdit
   if ((i = aTexte.Pos("\\rtf")) != 0)
      {
      int iAncienneTaille;
      //On se positionne avant le mot clè qui suit \rtfx
      do
         i++;
         while (aTexte[i] != '\\');

      //On ajoute les contrôles qui ont été effacés par le TRichEdit
      iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_LARG_FEUILLE + AnsiString(lArrond(m_PapierL*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_HAUT_FEUILLE + AnsiString(lArrond(m_PapierH*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_MARG_G + AnsiString(lArrond(m_MargeG*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_MARG_D + AnsiString(lArrond(m_MargeD*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_MARG_H + AnsiString(lArrond(m_MargeH*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_MARG_B + AnsiString(lArrond(m_MargeB*1440/MM_PER_INCH)), i);

      if (!bIsPortrait)
         {
         i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
         aTexte.Insert(DELIMIT_SECT_PAYSAGE, i);
         }

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_HAUT_EN_TETE + AnsiString(lArrond(m_dPositionEnTete*1440/MM_PER_INCH)), i);

      i += aTexte.Length() - iAncienneTaille;        iAncienneTaille = aTexte.Length();
      aTexte.Insert(DELIMIT_HAUT_PIED_DE_PAGE + AnsiString(lArrond(m_dPositionPiedDePage*1440/MM_PER_INCH)), i);
      }

   //On supprime la section Generator (car sous Open Office, les en-têtes et pied de page ne s'affichent par lorsqu'elle est présente.)
   GereRTF.SupprimerSection(GENERATOR, &aTexte);

   //Récupération de l'en-tête au format RTF et intégration au corps
   ssTexte = new TStringStream(EmptyStr);
   m_RE_EnTete->Lines->SaveToStream(ssTexte);
   aTexteEnTete.SetLength(ssTexte->Size);
   ssTexte->Position = 0;
   ssTexte->Read(aTexteEnTete.c_str(), ssTexte->Size);
   delete ssTexte; ssTexte = NULL;
   GereRTF.EnregistrerSection(&aTexte,EN_TETE,aTexteEnTete.Trim());

   //Récupération du pied de page au format RTF et intégration au corps
   ssTexte = new TStringStream(EmptyStr);
   m_RE_PiedDePage->Lines->SaveToStream(ssTexte);
   aTextePiedDePage.SetLength(ssTexte->Size);
   ssTexte->Position = 0;
   ssTexte->Read(aTextePiedDePage.c_str(), ssTexte->Size);
   delete ssTexte; ssTexte = NULL;
   GereRTF.EnregistrerSection(&aTexte,PIED_DE_PAGE,aTextePiedDePage.Trim());

   }
catch(Exception &e)
   {
   EICDisplayException(TAG(130), e);
   }
return aTexte;
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::SaveToFile(const AnsiString &aFileName)
{
TFileStream *fsTexte = NULL;
AnsiString aRTF;
try
   {
   aRTF = SaveToString();

   //Sauvegarde
   fsTexte = new TFileStream(aFileName, fmCreate);
   fsTexte->Write(aRTF.c_str(), aRTF.Length());
   delete fsTexte; fsTexte = NULL;
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(135), e);
   }
delete fsTexte;     fsTexte = NULL;
}


//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetReadOnly( bool bReadOnly )
{
try
   {
   m_ReadOnly                = bReadOnly;
   m_RE_EnTete->ReadOnly     = bReadOnly;
   m_RE_Corps->ReadOnly      = bReadOnly;
   m_RE_PiedDePage->ReadOnly = bReadOnly;
   Color =  bReadOnly ? clBtnFace : clWindow;
   Repaint();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(140), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetPlainText( bool bPlainText )
{
  m_PlainText                = bPlainText;
  m_RE_EnTete->PlainText     = bPlainText;
  m_RE_Corps->PlainText      = bPlainText;
  m_RE_PiedDePage->PlainText = bPlainText;
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetAfficherEnTeteEtPiedDePage(bool bAfficherEnTeteEtPiedDePage)
{
try
   {
   if (bAfficherEnTeteEtPiedDePage == m_AfficherEnTeteEtPiedDePage)
      return;

   m_AfficherEnTeteEtPiedDePage = bAfficherEnTeteEtPiedDePage;
   m_CGB_EnTete->Visible        = bAfficherEnTeteEtPiedDePage;
   m_CGB_PiedDePage->Visible    = bAfficherEnTeteEtPiedDePage;

   AjusterHauteur(m_RE_EnTete);
   AjusterHauteur(m_RE_PiedDePage);

   PositionnerPanelRichEdit();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(160), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetColor( TColor eColor)
{
try
   {
   m_Color                 = eColor;
   inherited::Color        = eColor;
  SendMessage(m_RE_EnTete->Handle, EM_SETBKGNDCOLOR, 0, ColorToRGB(eColor));

   m_RE_EnTete->Color      = eColor;
   m_RE_PiedDePage->Color  = eColor;
   m_RE_Corps->Color       = eColor;
   m_CGB_EnTete->Color     = eColor;
   m_CGB_PiedDePage->Color = eColor;
   Invalidate();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(170), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetHideSelection(bool bHideSelection)
{
  m_HideSelection                = bHideSelection;
  m_RE_EnTete->HideSelection     = bHideSelection;
  m_RE_PiedDePage->HideSelection = bHideSelection;
  m_RE_Corps->HideSelection      = bHideSelection;
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetWantReturns(bool bWantReturns)
{
  m_WantReturns                = bWantReturns;
  m_RE_EnTete->WantReturns     = bWantReturns;
  m_RE_PiedDePage->WantReturns = bWantReturns;
  m_RE_Corps->WantReturns      = bWantReturns;
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetWantTabs(bool bWantTabs)
{
  m_WantTabs                = bWantTabs;
  m_RE_EnTete->WantTabs     = bWantTabs;
  m_RE_PiedDePage->WantTabs = bWantTabs;
  m_RE_Corps->WantTabs      = bWantTabs;
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetWordWrap(bool bWordWrap)
{
  m_WordWrap                = bWordWrap;
  m_RE_EnTete->WordWrap     = bWordWrap;
  m_RE_PiedDePage->WordWrap = bWordWrap;
  m_RE_Corps->WordWrap      = bWordWrap;
}
//---------------------------------------------------------------------------
bool __fastcall CRtfEdit::GetModified()
{
  m_Modified =  m_RE_EnTete->Modified ||m_RE_PiedDePage->Modified || m_RE_Corps->Modified;
  return m_Modified;
}
//---------------------------------------------------------------------------
bool __fastcall CRtfEdit::GetCanUndo()
{
  return m_RE_DernierModifie->CanUndo;
}
/*******************************************************************************
void __fastcall CRtfEdit::RichEditChange(TObject *Sender)

Fonction : Executée lorsque l'un des trois RichEdit change

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::RichEditChange(TObject *Sender)
{
try
   {
   if (m_AfficherEnTeteEtPiedDePage && (Sender == m_RE_EnTete || Sender == m_RE_PiedDePage)
       /*|| Sender == m_RE_Corps*/)
      {
      AjusterHauteur((TRichEdit2*)Sender);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(140), e);
   }
  m_RE_DernierModifie = (TRichEditSansAutoScroll*)Sender;
  if (m_OnChange)
    m_OnChange(this, (TRichEditSansAutoScroll*)Sender);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::RichEditKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
try
   {
/*
   //SI des contraintes de hauteur sont gérées, on annule la dernière saisie lorsque celle-ci
   //a trop augmentée la hauteur du composant.
   //Hélàs, c'est tout le texte qui vient d'être saisie qui est annulé, pouvant entrainer l'annulation
   //de plusieurs lignes. Par conséquent, avant chaque saut de ligne, on clôt le groupe d'annulation.
   //De cette manière, on ne peut pas annuler plus d'une ligne.
   if (Key == 13
       &&  (   Sender == m_RE_EnTete && m_ContrainteTaille->HauteurEnTeteMax != SANS_CONTRAINTE
            || Sender == m_RE_Corps && m_ContrainteTaille->HauteurCorpsMax != SANS_CONTRAINTE
            || Sender == m_RE_PiedDePage && m_ContrainteTaille->HauteurPiedMax != SANS_CONTRAINTE))
      SendMessage(((TRichEdit2*)Sender)->Handle, EM_STOPGROUPTYPING,  0, 0);*/

   if (m_OnKeyDown)
      m_OnKeyDown((TObject*)this, (TRichEdit2*)Sender, Key, Shift);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(150), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::RichEditKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
{
  if (m_OnKeyUp)
    m_OnKeyUp((TObject*)this,(TRichEdit2*)Sender,Key,Shift);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::RichEditKeyPress(TObject *Sender,  char &Key)
{
  if (m_OnKeyPress)
    m_OnKeyPress((TObject*)this,(TRichEdit2*)Sender,Key);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::RichEditSelectionChange(TObject *Sender)
{
try
   {
   if (m_OnSelectionChange)
      m_OnSelectionChange((TObject*)this,(TRichEdit2*)Sender);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(340), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::RichEditOnEnter(TObject *Sender)
{
  m_RE_Courant = (TRichEditSansAutoScroll*)Sender;

  if (m_RE_Courant != m_RE_EnTete)
     m_RE_EnTete->SelLength = 0;

  if (m_RE_Courant != m_RE_Corps)
     m_RE_Corps->SelLength = 0;

  if (m_RE_Courant != m_RE_PiedDePage)
     m_RE_PiedDePage->SelLength = 0;
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::RequestSize (Messages::TMessage &Message)
{
try
   {
   if(Message.Msg == WM_NOTIFY)
      {
      if(((NMHDR*)Message.LParam)->code == EN_REQUESTRESIZE)
         {
         REQRESIZE *Taille = ((REQRESIZE*)Message.LParam);
         _HauteurVoulueParRichEdit = Taille->rc.bottom - Taille->rc.top;
         }
      }
   else if(Message.Msg == WM_SIZE)
      {
      int iHauteurMax = (m_ContrainteTaille->HauteurCorpsMax != SANS_CONTRAINTE ? m_ContrainteTaille->HauteurCorpsMax * Screen->PixelsPerInch / MM_PER_INCH : SANS_CONTRAINTE);

//      m_PapierL = lArrond((double)Width / Screen->PixelsPerInch * MM_PER_INCH);
      PositionnerPanelRichEdit();

      if (m_AfficherEnTeteEtPiedDePage)
         m_RE_Corps->Height = Height - m_CGB_EnTete->Top - m_CGB_EnTete->Height - m_CGB_PiedDePage->Height -( m_dPositionPiedDePage* Screen->PixelsPerInch / MM_PER_INCH) ;
      else
         m_RE_Corps->Height = Height - (m_MargeB + m_MargeH)* Screen->PixelsPerInch / MM_PER_INCH;

      if (iHauteurMax != SANS_CONTRAINTE)
         m_RE_Corps->Height = min(iHauteurMax,  m_RE_Corps->Height);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(350), e);
   }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::MyWndProcParentEnTete(Messages::TMessage &Message)
{
try
   {
   RequestSize(Message);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(360), e);
   }
  m_SveWindowProcEnTete(Message);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::MyWndProcParentPiedDePage(Messages::TMessage &Message)
{
try
   {
   RequestSize(Message);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(370), e);
   }
  m_SveWindowProcPiedDePage(Message);
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::MyWndProcParentCorps(Messages::TMessage &Message)
{
try
   {
   RequestSize(Message);

   if(m_OnResizeRequest
      && Message.Msg == WM_NOTIFY && ((REQRESIZE*)Message.LParam)->nmhdr.code == EN_REQUESTRESIZE)
      {
      TRect Rect;
      GetRectRequest(&Rect, _HauteurVoulueParRichEdit);
      if (Width != Rect.Right || Height != Rect.Bottom)
         m_OnResizeRequest(this, Rect);
      }
  }
catch(Exception &e)
   {
   EICDisplayException(TAG(380), e);
   }
  m_SveWindowProcCorps(Message);
}
//---------------------------------------------------------------------------
int __fastcall CRtfEdit::GetHauteurTotaleNecessaire() const
{
try
   {
   _HauteurVoulueParRichEdit = GetHauteurCorpsNecessaire() + m_CGB_EnTete->Height + m_CGB_PiedDePage->Height;
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(390), e);
   }

return _HauteurVoulueParRichEdit;
}
//---------------------------------------------------------------------------
int __fastcall CRtfEdit::GetHauteurCorpsNecessaire() const
{
try
   {
   ::SendMessage(m_RE_Corps->Handle, EM_REQUESTRESIZE, 0, 0);  //permet d'initialiser _HauteurVoulueParRichEdit
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(400), e);
   }

return _HauteurVoulueParRichEdit;
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::Undo()
{
  try
  {
    if (m_RE_DernierModifie)
      m_RE_DernierModifie->Undo();
  }
  catch (Exception &e)
  {
    EICDisplayException(TAG(410),e);
  }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::ClearUndo()
{
  try
  {
    m_RE_EnTete->ClearUndo();
    m_RE_Corps->ClearUndo();
    m_RE_PiedDePage->ClearUndo();
  }
  catch (Exception &e)
  {
    EICDisplayException(TAG(420),e);
  }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::PositionnerPanelRichEdit()
{
  try
  {
    //On positionne le GroupBox d'en-tête de manière à ce que la première ligne du RichEdit soit bien placée
    m_CGB_EnTete->Top = m_AfficherEnTeteEtPiedDePage ? max(0L, lArrond(m_dPositionEnTete * Screen->PixelsPerInch / MM_PER_INCH) - (m_RE_EnTete->ClientOrigin.y - m_CGB_EnTete->ClientOrigin.y))
                                                     : 0;
    m_RE_Corps->Top = m_AfficherEnTeteEtPiedDePage ? max(m_CGB_EnTete->Top + m_CGB_EnTete->Height, (int)lArrond((double)m_MargeH * Screen->PixelsPerInch / MM_PER_INCH))
                                                   : lArrond((double)m_MargeH * Screen->PixelsPerInch / MM_PER_INCH);
    m_CGB_PiedDePage->Top    = Height - m_CGB_PiedDePage->Height - lArrond(m_dPositionPiedDePage * Screen->PixelsPerInch / MM_PER_INCH);
    m_CGB_EnTete->Width      = Width - lArrond((double)(m_MargeG + m_MargeD)* Screen->PixelsPerInch / MM_PER_INCH) + 2 * DECALAGE_X_RICH_EDIT;
    m_RE_Corps->Width        = Width - lArrond((double)(m_MargeG + m_MargeD)* Screen->PixelsPerInch / MM_PER_INCH) ;
    m_CGB_PiedDePage->Width  = m_CGB_EnTete->Width;
    m_CGB_EnTete->Left       = lArrond((double)m_MargeG * Screen->PixelsPerInch / MM_PER_INCH) - DECALAGE_X_RICH_EDIT;
    m_RE_Corps->Left         = lArrond((double)m_MargeG * Screen->PixelsPerInch / MM_PER_INCH);
    m_CGB_PiedDePage->Left   = m_CGB_EnTete->Left;
  }
  catch (Exception &e)
  {
    EICDisplayException(TAG(430),e);
  }
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetMargeG(int MargeG)
{
  if (m_ContrainteTaille->MargeG != SANS_CONTRAINTE)
     return;

  m_MargeG = MargeG;

  if(!ComponentState.Contains(csLoading))
     PositionnerPanelRichEdit();
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetMargeD(int MargeD)
{
  if (m_ContrainteTaille->MargeD != SANS_CONTRAINTE)
     return;

  m_MargeD = MargeD;

  if(!ComponentState.Contains(csLoading))
     PositionnerPanelRichEdit();
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetMargeH(int MargeH)
{
  if (m_ContrainteTaille->MargeH != SANS_CONTRAINTE)
     return;

  m_MargeH = MargeH;
  if(!ComponentState.Contains(csLoading) &&   m_OnResizeRequest)
     {
     TRect Rect;

     PositionnerPanelRichEdit();

     GetRectRequest(&Rect);
     m_OnResizeRequest(this, Rect);
     }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetMargeB(int MargeB)
{
  if (m_ContrainteTaille->MargeB != SANS_CONTRAINTE)
     return;

  m_MargeB = MargeB;
  if(!ComponentState.Contains(csLoading) &&   m_OnResizeRequest)
     {
     TRect Rect;

     PositionnerPanelRichEdit();

     GetRectRequest(&Rect);
     m_OnResizeRequest(this, Rect);
     }
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetPapierH(int PapierH)
{
FormatPapierChange(-1, PapierH);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetPapierL(int PapierL)
{
FormatPapierChange(PapierL, -1);
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetPositionEnTete(double dPositionEnTete)
{
  m_dPositionEnTete = dPositionEnTete;
  if(!ComponentState.Contains(csLoading) &&   m_OnResizeRequest)
     {
     TRect Rect;
     GetRectRequest(&Rect);
     m_OnResizeRequest(this, Rect);
     }
  if(!ComponentState.Contains(csLoading))
     PositionnerPanelRichEdit();
}
//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetPositionPiedDePage(double dPositionPiedDePage)
{
  m_dPositionPiedDePage = dPositionPiedDePage;
  if(!ComponentState.Contains(csLoading) &&   m_OnResizeRequest)
     {
     TRect Rect;
     GetRectRequest(&Rect);
     m_OnResizeRequest(this, Rect);
     }
  if(!ComponentState.Contains(csLoading))
     PositionnerPanelRichEdit();
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::GetRectRequest(TRect *ReqRequest, int iHauteurVoulueParRichEdit)
{
      int iHauteurImprimableParPage, iHauteurCorpsParPage, iNbPages;
      CalculHauteurs(&iHauteurVoulueParRichEdit,&iHauteurImprimableParPage,&iHauteurCorpsParPage);
      iNbPages = GetNbPages(iHauteurVoulueParRichEdit, iHauteurCorpsParPage);
      ReqRequest->top = 0;
      ReqRequest->left = 0;
      if (AfficherEnTeteEtPiedDePage)
        ReqRequest->bottom = ceil(max((double)m_CGB_EnTete->Top + m_CGB_EnTete->Height,
                                  m_MargeH * Screen->PixelsPerInch / MM_PER_INCH)
                                + iHauteurCorpsParPage * iNbPages
                                + max(m_dPositionPiedDePage * Screen->PixelsPerInch / MM_PER_INCH + m_CGB_PiedDePage->Height,
                                      m_MargeB * Screen->PixelsPerInch / MM_PER_INCH));
      else
        ReqRequest->bottom = m_MargeH * Screen->PixelsPerInch / MM_PER_INCH
                           + iHauteurCorpsParPage * iNbPages
                           + m_MargeB * Screen->PixelsPerInch / MM_PER_INCH;
      ReqRequest->right = lArrond(m_PapierL * Screen->PixelsPerInch / MM_PER_INCH);
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::Clear()
{
  m_RE_EnTete->Clear();
  m_RE_Corps->Clear();
  m_RE_PiedDePage->Clear();
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::SetFormatPapier( enum NOM_FORMAT_PAPIER eFormat)
{
  TFormatPapier Format;
  try
  {
    TTaillePapier Point = Format.GetTaillePapier(eFormat,MILLIMETRES);
    m_Format = eFormat;
    if (ComponentState.Contains(csDesigning))
       {
       //En conception => on redimensionne directement le composant
       PapierL = Point.dx;
       PapierH = Point.dy;
       }
    else
       {
       m_PapierL = Point.dx;
       m_PapierH = Point.dy;

       if(!ComponentState.Contains(csLoading) &&   m_OnResizeRequest)
          {
          TRect Rect;
          GetRectRequest(&Rect);
          m_OnResizeRequest(this, Rect);
          }
       if(!ComponentState.Contains(csLoading))
          PositionnerPanelRichEdit();
       }
  }
  catch (Exception &e)
  {
    EICDisplayException(TAG(540),e);
  }
}

//---------------------------------------------------------------------------
void __fastcall CRtfEdit::CalculHauteurs(int *iHauteurVoulueParRichEdit, int *iHauteurImprimableParPage, int *iHauteurCorpsParPage) const
{
HDC  hdcImp = NULL;
unsigned long lTmp;
int MargeHautNonImprimableEnPix = 0, MargeBasNonImprimableEnPix = 0;
try
   {
   if (m_OnGetHDCImp)
      m_OnGetHDCImp((TObject*)this, &hdcImp);
   else if (Printer()->Printers->Count)
      hdcImp = Printer()->Handle;
   else
      hdcImp = NULL;

   if (!*iHauteurVoulueParRichEdit)
      *iHauteurVoulueParRichEdit = GetHauteurCorpsNecessaire();

   if (hdcImp)
      {
      int  NbPixParPouceY;
      NbPixParPouceY = GetDeviceCaps(hdcImp, LOGPIXELSY);
      MargeHautNonImprimableEnPix = lArrond(GetDeviceCaps(hdcImp, PHYSICALOFFSETY) * Screen->PixelsPerInch / NbPixParPouceY);
      MargeBasNonImprimableEnPix  = lArrond((   GetDeviceCaps(hdcImp, PHYSICALHEIGHT)
                                              - GetDeviceCaps(hdcImp, PHYSICALOFFSETY)
                                              - GetDeviceCaps(hdcImp, VERTRES)) * Screen->PixelsPerInch / NbPixParPouceY);

      }
   *iHauteurImprimableParPage = m_PapierH * Screen->PixelsPerInch / MM_PER_INCH
                              - MargeHautNonImprimableEnPix
                              - MargeBasNonImprimableEnPix;

   if (AfficherEnTeteEtPiedDePage)
      *iHauteurCorpsParPage = *iHauteurImprimableParPage - (max(lArrond(m_RE_EnTete->Height + dPositionEnTete * Screen->PixelsPerInch / MM_PER_INCH),
                                                               lArrond(m_MargeH * Screen->PixelsPerInch / MM_PER_INCH))
                                                             - MargeHautNonImprimableEnPix)
                                                         - (max(lArrond(m_RE_PiedDePage->Height + dPositionPiedDePage * Screen->PixelsPerInch / MM_PER_INCH),
                                                               lArrond(m_MargeB * Screen->PixelsPerInch / MM_PER_INCH))
                                                             - MargeBasNonImprimableEnPix);
   else
      *iHauteurCorpsParPage = *iHauteurImprimableParPage - (lArrond(m_MargeH * Screen->PixelsPerInch / MM_PER_INCH)
                                                          - MargeHautNonImprimableEnPix)
                                                         - (lArrond(m_MargeB * Screen->PixelsPerInch / MM_PER_INCH)
                                                            - MargeBasNonImprimableEnPix);
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(560), e);
   }
}
//---------------------------------------------------------------------------
int __fastcall CRtfEdit::GetNbPages(int iHauteurVoulueParRichEdit,int iHauteurCorpsParPage) const
{
  int iHauteurImprimableParPage;
  if (!iHauteurVoulueParRichEdit && !iHauteurCorpsParPage)
    CalculHauteurs(&iHauteurVoulueParRichEdit,&iHauteurImprimableParPage,&iHauteurCorpsParPage);
  ASSERT(iHauteurCorpsParPage);
  return  ceil((double) iHauteurVoulueParRichEdit / iHauteurCorpsParPage);
}

unsigned long __stdcall EditStreamInCallback(unsigned long dwCookie,
                                             unsigned char* pbBuff, long cb,
                                             long *pcb)
   {
   TStringStream *theStream = NULL;
   long Result;
   long dataAvail;
   theStream = (TStringStream*)dwCookie;

    dataAvail = theStream->Size - theStream->Position;
    Result = 0;
    if (dataAvail <= cb)
       {
       *pcb = theStream->Read(pbBuff, dataAvail);
       if (*pcb != dataAvail)
          Result = UINT(E_FAIL);
       }
    else
      {
      *pcb = theStream->Read(pbBuff, cb);
      if (*pcb != cb)
        Result = UINT(E_FAIL);
      }
  return  Result;
  }


/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
bool __fastcall CRtfEdit::InsertImageFromFile(const AnsiString &aFileName)
{
TStringStream *SS = NULL;
EDITSTREAM sEditStream;
TPicture *Picture = NULL;
bool bInsertionReussie = false;
AnsiString aErreur;
try
   {
   Picture = new TPicture();

   try
      {
      Picture->LoadFromFile(aFileName);

      if (dynamic_cast<Graphics::TBitmap *>(Picture->Graphic))
         {
         SS  = new  TStringStream(BitmapVersRTF(Picture->Bitmap));

         sEditStream.dwCookie = (long)SS;
         sEditStream.dwError = 0;
         sEditStream.pfnCallback = EditStreamInCallback;
         m_RE_Courant->Perform(EM_STREAMIN, SF_RTF | SFF_SELECTION, (int)&sEditStream);

         bInsertionReussie = (sEditStream.dwError == 0);
         }
      }
   catch(EInvalidGraphic &e)
      {
      //L'image n'est ni un BMP, ni un icône, ni un MetaFile
      aErreur = e.Message;
      }

   if (Picture)
      {
      delete Picture;
      Picture = NULL;
      }

   if (!bInsertionReussie && !aErreur.IsEmpty())
      {
      Application->MessageBox(aErreur.c_str(), "Erreur d'insertion d'image", MB_OK | MB_ICONERROR);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(570), e);
   }


if (SS)
   {
   delete SS; SS = NULL ;
   }
return bInsertionReussie;
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::ContrainteHauteurChange(TObject *Sender)
{
try
   {
   RichEditChange(m_RE_EnTete); //Réduit la taille du composant si nécessaire
   SendMessage(m_RE_Corps->Handle, WM_SIZE, 0, 0);
   RichEditChange(m_RE_PiedDePage); //Réduit la taille du composant si nécessaire
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(580), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::ContrainteMargeChange(TObject *Sender)
{
try
   {
   if (m_ContrainteTaille->MargeG != SANS_CONTRAINTE)
      m_MargeG = m_ContrainteTaille->MargeG;
   if (m_ContrainteTaille->MargeD != SANS_CONTRAINTE)
      m_MargeD = m_ContrainteTaille->MargeD;
   if (m_ContrainteTaille->MargeH != SANS_CONTRAINTE)
      m_MargeH = m_ContrainteTaille->MargeH;
   if (m_ContrainteTaille->MargeB != SANS_CONTRAINTE)
      m_MargeB = m_ContrainteTaille->MargeB;

   PositionnerPanelRichEdit();
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(585), e);
   }
}
/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::WMCreate(TMessage &Msg)
{
try
   {
   if(!ComponentState.Contains(csDesigning))
      {
      //On active l'événement REQUESTRESIZE
      ::SendMessage(m_RE_EnTete    ->Handle, EM_SETEVENTMASK, 0, ::SendMessage(m_RE_EnTete    ->Handle, EM_GETEVENTMASK, 0, 0) | ENM_REQUESTRESIZE);
      ::SendMessage(m_RE_Corps     ->Handle, EM_SETEVENTMASK, 0, ::SendMessage(m_RE_Corps     ->Handle, EM_GETEVENTMASK, 0, 0) | ENM_REQUESTRESIZE);
      ::SendMessage(m_RE_PiedDePage->Handle, EM_SETEVENTMASK, 0, ::SendMessage(m_RE_PiedDePage->Handle, EM_GETEVENTMASK, 0, 0) | ENM_REQUESTRESIZE);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(590), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
bool __fastcall CRtfEdit::GetIsPortrait()
{
return (m_PapierL < m_PapierH);
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::SetIsPortrait(bool bIsPortrait)
{
try
   {
   //Si on change l'orientation
//   if (m_bIsPortrait != bIsPortrait)
      {
//      m_bIsPortrait = bIsPortrait;
      FormatPapierChange(bIsPortrait ? min(m_PapierL, m_PapierH) : max(m_PapierL, m_PapierH),
                         bIsPortrait ? max(m_PapierL, m_PapierH) : min(m_PapierL, m_PapierH));
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(620), e);
   }
}

/*******************************************************************************
void __fastcall CRtfEdit::FormatPapierChange(int iLargeur, int iHauteur)

Fonction : Redimensionne le composant lorsque le format de papier change.

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::FormatPapierChange(int iLargeur, int iHauteur)
{
TTaillePapier TaillePapier;
try
   {
   TaillePapier.dx = (iLargeur > 0 ? iLargeur : m_PapierL);
   TaillePapier.dy = (iHauteur > 0 ? iHauteur : m_PapierH);
   m_PapierL = TaillePapier.dx;
   m_PapierH = TaillePapier.dy;
   m_Format = FormatDuPapier.GetFormatPapier(&TaillePapier, MILLIMETRES);

   //En conception => Le composant se redimensionne
   if (ComponentState.Contains(csDesigning))
      {
      Width  = m_PapierL * Screen->PixelsPerInch / MM_PER_INCH;
      Height = m_PapierH * Screen->PixelsPerInch / MM_PER_INCH;
      PositionnerPanelRichEdit();
      }
   //A l'éxecution, si le chargement est achevé => On demande un repositionnement du composant
   else if (!ComponentState.Contains(csLoading) && m_OnResizeRequest)
      {
      TRect Rect;
      GetRectRequest(&Rect);
      m_OnResizeRequest(this, Rect);
      }
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(630), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::AjusterHauteur(TRichEdit2 *RichEdit)
{
int iHauteurMax = SANS_CONTRAINTE;
int iHauteurFinale = 0;
try
   {
   ::SendMessage(RichEdit->Handle, EM_REQUESTRESIZE, 0, 0);  //permet d'initialiser _HauteurVoulueParRichEdit

   if (RichEdit == m_RE_EnTete && m_ContrainteTaille->HauteurEnTeteMax != SANS_CONTRAINTE)
      iHauteurMax = m_ContrainteTaille->HauteurEnTeteMax * Screen->PixelsPerInch / MM_PER_INCH;
//      else if (RichEdit == m_RE_Corps && m_ContrainteTaille->HauteurCorpsMax != SANS_CONTRAINTE)
//         iHauteurMax = m_ContrainteTaille->HauteurCorpsMax * Screen->PixelsPerInch / MM_PER_INCH;
   else if (RichEdit == m_RE_PiedDePage && m_ContrainteTaille->HauteurPiedMax != SANS_CONTRAINTE)
      iHauteurMax = m_ContrainteTaille->HauteurPiedMax * Screen->PixelsPerInch / MM_PER_INCH;

   //Si une hauteur maximum, non nulle, est imposée et si le corps n'est pas à afficher, on dimensionne
   //automatiquement l'en-tête et le pied de page à leur hauteurs maximums.
   if (iHauteurMax > 0 && !m_ContrainteTaille->HauteurCorpsMax)
      iHauteurFinale = iHauteurMax;
   else if (iHauteurMax != SANS_CONTRAINTE && _HauteurVoulueParRichEdit > iHauteurMax)
      {
      if ((RichEdit == m_RE_EnTete || RichEdit == m_RE_PiedDePage)
          && (iHauteurMax <= 0 || !m_AfficherEnTeteEtPiedDePage))
         {
         iHauteurFinale = 0L;
         RichEdit->Parent->Visible = false;
         }
//         else if (RichEdit == m_RE_Corps && iHauteurMax <= 0)
//            RichEdit->Visible = false;
      else
//            ::SendMessage(RichEdit->Handle, EM_UNDO, 0, 0);
         iHauteurFinale = min(_HauteurVoulueParRichEdit, iHauteurMax);
      }
   else
      iHauteurFinale = _HauteurVoulueParRichEdit;

   RichEdit->Parent->Height = iHauteurFinale;
   if ((RichEdit == m_RE_EnTete || RichEdit == m_RE_PiedDePage) && RichEdit->Parent->Visible)
      RichEdit->Parent->Height += 20; //Hauteur du CGroupBox = hauteur du TRichEdit + 20
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(640), e);
   }
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres modifiés :

Valeur retournée :
*******************************************************************************/
TPopupMenu* __fastcall CRtfEdit::MonGetPopupMenu()
{
return m_PopupMenu;
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres modifiés :

Valeur retournée :
*******************************************************************************/
void __fastcall CRtfEdit::SetPopupMenu (TPopupMenu* PopupMenu)
{
try
   {
   if (PopupMenu == m_PopupMenu)
      return;

   m_PopupMenu                = PopupMenu;
   inherited::PopupMenu       = m_PopupMenu;
   m_RE_EnTete    ->PopupMenu = m_PopupMenu;
   m_RE_Corps     ->PopupMenu = m_PopupMenu;
   m_RE_PiedDePage->PopupMenu = m_PopupMenu;
   }
catch(Exception &e)
   {
   EICDisplayException(TAG(650), e);
   }
}

namespace Crtfedit
{
   void __fastcall PACKAGE Register()
   {
       TComponentClass classes[1] = {__classid(CRtfEdit)};
       RegisterComponents("EIC Ctrlstd", classes, 0);
   }
}

